home *** CD-ROM | disk | FTP | other *** search
/ Software Vault: The Gold Collection / Software Vault - The Gold Collection (American Databankers) (1993).ISO / cdr26 / netprog.zip / NETPROG.TAR / tftp / file.c < prev    next >
C/C++ Source or Header  |  1989-12-17  |  5KB  |  195 lines

  1. /*
  2.  * Routines to open/close/read/write the local file.
  3.  * For "binary" (octet) transmissions, we use the UNIX open/read/write
  4.  * system calls (or their equivalent).
  5.  * For "ascii" (netascii) transmissions, we use the UNIX standard i/o routines
  6.  * fopen/getc/putc (or their equivalent).
  7.  */
  8.  
  9. #include    "defs.h"
  10.  
  11. /*
  12.  * The following are used by the functions in this file only.
  13.  */
  14.  
  15. static int    lastcr   = 0;    /* 1 if last character was a carriage-return */
  16. static int    nextchar = 0;
  17.  
  18. /*
  19.  * Open the local file for reading or writing.
  20.  * Return a FILE pointer, or NULL on error.
  21.  */
  22.  
  23. FILE *
  24. file_open(fname, mode, initblknum)
  25. char    *fname;
  26. char    *mode;        /* for fopen() - "r" or "w" */
  27. int    initblknum;
  28. {
  29.     register FILE    *fp;
  30.  
  31.     if (strcmp(fname, "-") == 0)
  32.         fp = stdout;
  33.     else if ( (fp = fopen(fname, mode)) == NULL)
  34.         return((FILE *) 0);
  35.  
  36.     nextblknum = initblknum;    /* for first data packet or first ACK */
  37.     lastcr     = 0;            /* for file_write() */
  38.     nextchar   = -1;        /* for file_read() */
  39.  
  40.     DEBUG2("file_open: opened %s, mode = %s", fname, mode);
  41.  
  42.     return(fp);
  43. }
  44.  
  45. /*
  46.  * Close the local file.
  47.  * This causes the standard i/o system to flush its buffers for this file.
  48.  */
  49.  
  50. file_close(fp)
  51. FILE    *fp;
  52. {
  53.     if (lastcr)
  54.         err_dump("final character was a CR");
  55.     if (nextchar >= 0)
  56.         err_dump("nextchar >= 0");
  57.  
  58.     if (fp == stdout)
  59.         return;        /* don't close standard output */
  60.     else if (fclose(fp) == EOF)
  61.         err_dump("fclose error");
  62. }
  63.  
  64. /*
  65.  * Read data from the local file.
  66.  * Here is where we handle any conversion between the file's mode
  67.  * on the local system and the network mode.
  68.  *
  69.  * Return the number of bytes read (between 1 and maxnbytes, inclusive)
  70.  * or 0 on EOF.
  71.  */
  72.  
  73. int
  74. file_read(fp, ptr, maxnbytes, mode)
  75. FILE        *fp;
  76. register char    *ptr;
  77. register int    maxnbytes;
  78. int        mode;
  79. {
  80.     register int    c, count;
  81.  
  82.     if (mode == MODE_BINARY) {
  83.         count = read(fileno(fp), ptr, maxnbytes);
  84.         if (count < 0)
  85.             err_dump("read error on local file");
  86.  
  87.         return(count);        /* will be 0 on EOF */
  88.  
  89.     } else if (mode == MODE_ASCII) {
  90.         /*
  91.          * For files that are transferred in netascii, we must
  92.          * perform the reverse conversions that file_write() does.
  93.          * Note that we have to use the global "nextchar" to
  94.          * remember if the next character to output is a linefeed
  95.          * or a null, since the second byte of a 2-byte sequence
  96.          * may not fit in the current buffer, and may have to go
  97.          * as the first byte of the next buffer (i.e., we have to
  98.          * remember this fact from one call to the next).
  99.          */
  100.  
  101.         for (count = 0; count < maxnbytes; count++) {
  102.             if (nextchar >= 0) {
  103.                 *ptr++ = nextchar;
  104.                 nextchar = -1;
  105.                 continue;
  106.             }
  107.  
  108.             c = getc(fp);
  109.  
  110.             if (c == EOF) {    /* EOF return means eof or error */
  111.                 if (ferror(fp))
  112.                    err_dump("read err from getc on local file");
  113.                 return(count);
  114.  
  115.             } else if (c == '\n') {
  116.                 c = '\r';        /* newline -> CR,LF */
  117.                 nextchar = '\n';
  118.  
  119.             } else if (c == '\r') {
  120.                 nextchar = '\0';    /* CR -> CR,NULL */
  121.  
  122.             } else
  123.                 nextchar = -1;
  124.  
  125.             *ptr++ = c;
  126.         }
  127.  
  128.         return(count);
  129.     } else
  130.         err_dump("unknown MODE value");
  131.  
  132.     /* NOTREACHED */
  133. }
  134.  
  135. /*
  136.  * Write data to the local file.
  137.  * Here is where we handle any conversion between the mode of the
  138.  * file on the network and the local system's conventions.
  139.  */
  140.  
  141. file_write(fp, ptr, nbytes, mode)
  142. FILE        *fp;
  143. register char    *ptr;
  144. register int    nbytes;
  145. int        mode;
  146. {
  147.     register int    c, i;
  148.  
  149.     if (mode == MODE_BINARY) {
  150.         /*
  151.          * For binary mode files, no conversion is required.
  152.          */
  153.  
  154.         i = write(fileno(fp), ptr, nbytes);
  155.         if (i != nbytes)
  156.             err_dump("write error to local file, i = %d", i);
  157.  
  158.     } else if (mode == MODE_ASCII) {
  159.         /*
  160.          * For files that are transferred in netascii, we must
  161.          * perform the following conversions:
  162.          *
  163.          *    CR,LF             ->  newline = '\n'
  164.          *    CR,NULL           ->  CR      = '\r'
  165.          *    CR,anything_else  ->  undefined (we don't allow this)
  166.          *
  167.          * Note that we have to use the global "lastcr" to remember
  168.          * if the last character was a carriage-return or not,
  169.          * since if the last character of a buffer is a CR, we have
  170.          * to remember that when we're called for the next buffer.
  171.          */
  172.  
  173.         for (i = 0; i < nbytes; i++) {
  174.             c = *ptr++;
  175.             if (lastcr) {
  176.                 if (c == '\n')
  177.                     c = '\n';
  178.                 else if (c == '\0')
  179.                     c = '\r';
  180.                 else
  181.                     err_dump("CR followed by 0x%02x", c);
  182.                 lastcr = 0;
  183.  
  184.             } else if (c == '\r') {
  185.                 lastcr = 1;
  186.                 continue;    /* get next character */
  187.             }
  188.  
  189.             if (putc(c, fp) == EOF)
  190.                 err_dump("write error from putc to local file");
  191.         }
  192.     } else
  193.         err_dump("unknown MODE value");
  194. }
  195.